package com.hoshiicloud.fileserver.controller;

import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.BeanUtils;
import com.hoshiicloud.fileserver.model.*;
import com.hoshiicloud.fileserver.service.FileObjectService;
import com.hoshiicloud.fileserver.util.ObsPictureProcessUtil;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM;

@RestController
@RequestMapping("/file")
@Api(tags = "文件操作")
@Slf4j
public class FileObjectController {
	@Autowired
	private FileObjectService fileObjectService;

	private final String BUCKET_NAME="obs-7d37";


	@RequestMapping(value = "/downloadFile",method = RequestMethod.GET,produces = MediaType.MULTIPART_FORM_DATA_VALUE)
	@ApiOperation(value = "下载一个文件",notes = "返回文件对象")
	public void downloadFile(@RequestParam("bucketName") String bucketName, @RequestParam("objectKey") String objectKey, HttpServletResponse response) throws Exception{
		Response<InputStream> result= fileObjectService.downloadFile(bucketName,objectKey);
		if(!result.isSuccess()){
			log.info("下载文件失败:"+result.getMsg());
			return;
		}
		InputStream in=null;
		try {
			OutputStream out = response.getOutputStream();
			in = result.getData();
			byte buffer[] = new byte[1024];
			int length = 0;
			while ((length = in.read(buffer)) >= 0){
				out.write(buffer,0,length);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	@ApiOperation(value = "feign上传一个文件", notes = "传入已存在objectKey时将会覆盖原文件",hidden = true)
	@ApiImplicitParams({
			@ApiImplicitParam(name = "bucketName",value = "存储空间名称，上传时指定的存储空间",paramType = "String",example = "obs-7d37"),
			@ApiImplicitParam(name = "objectKey",value = "文件key,上传时存储的对象key,如果key相同并且文件已存在，将覆盖文件，上传完毕后原样返回，如不传则使用文件MD5值。",paramType = "String"),
			@ApiImplicitParam(name = "fileName",value = "文件名,批量上传时需和key对应",paramType = "String"),
			@ApiImplicitParam(name = "folder",value = "文件夹路径",paramType = "String"),
			@ApiImplicitParam(name = "privateOwned",value = "对象私有读写,因没有设置的权限暂时无效",paramType = "Boolean",example = "false"),
			@ApiImplicitParam(name = "file",value = "文件",paramType = "formData",dataType = "MultipartFile"),
	})
	public Response<UploadFileResponse> uploadFile(@RequestParam("bucketName") String bucketName,@RequestParam("objectKey") String objectKey,@RequestParam("fileName") String fileName,@RequestParam("folder") String folder,@RequestParam("privateOwned") Boolean privateOwned , MultipartFile file) throws Exception {
		if (file == null || file.getSize() == 0) {
			return Response.failed("文件为空");
		}
		ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(file.getBytes()) ;
		InputStream fileInputStream = file.getInputStream();
		if (StringUtils.isBlank(objectKey)) {
			objectKey = DigestUtils.md5DigestAsHex(fileInputStream);
		}
		Response<UploadFileResponse> uploadResult = fileObjectService.uploadFile(bucketName, folder, objectKey,byteArrayInputStream,privateOwned);
		UploadFileResponse info = uploadResult.getData();
		if (info!=null) {
			info.setFileName(fileName);
		}
		return Response.data(info);
	}

	@RequestMapping(value = "/uploadOneFile", method = RequestMethod.POST)
	@ApiOperation(value = "上传一个文件", notes = "传入已存在objectKey时将会覆盖原文件",hidden = false)
	public Response<UploadFileTempRepsonse> uploadOneFile(UploadFileRequest param, MultipartFile file) throws Exception {
		if (file == null || file.getSize() == 0) {
			return Response.failed("文件为空");
		}
		String bucketName = param.getBucketName();
		String objectKey = param.getObjectKey();
		String folder = param.getFolder();
		ByteArrayInputStream temp=new ByteArrayInputStream(file.getBytes()) ;
		InputStream fileInputStream = file.getInputStream();
		if (StringUtils.isBlank(objectKey)) {
			objectKey = DigestUtils.md5DigestAsHex(fileInputStream);
		}
		String fileName=file.getOriginalFilename();
		String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
		//重新写为固定值
		bucketName=this.BUCKET_NAME;
		//拼接文件后缀名
		objectKey= UUID.randomUUID().toString()+"."+suffix;

		Response<UploadFileResponse> uploadResult = fileObjectService.uploadFile(bucketName, folder, objectKey, temp);


		if(!uploadResult.isSuccess()){
			return Response.failed(uploadResult.getMsg());
		}
		UploadFileResponse info = uploadResult.getData();
		if (info!=null) {
			info.setFileName(file.getOriginalFilename());
		}
		UploadFileTempRepsonse t=new UploadFileTempRepsonse();
		BeanUtils.copyProperties(info,t);
		return Response.data(t);
	}

	@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
	@ApiOperation(value = "上传多个文件", notes = "文件信息列表内不需传入bucketName，传入已存在objectKey时将会覆盖原文件", consumes = "multipart/form-data",hidden = true)
	public Response<UploadFilesResponse> uploadFiles(UploadFilesRequest param, MultipartFile[] files) {
		if (files == null || files.length == 0) {
			return Response.failed("文件列表为空");
		}

		List<UploadFileResponse> uploadFileInfoList = new ArrayList<UploadFileResponse>();
		int successCount = 0;
		// 指定的存储空间名称
		String bucketName = param.getBucketName();
		List<UploadFileRequest> fileList = param.getFileInfoList();
		for (MultipartFile file : files) {

			if (file.isEmpty()) {
				UploadFileResponse info = new UploadFileResponse(500, "文件为空");
				info.setFileName(file.getOriginalFilename());
				uploadFileInfoList.add(info);
			} else {
				String objectKey = null;
				String folder = param.getFolder();
				InputStream fileInputStream = null;
				try {
					fileInputStream = file.getInputStream();

					// 查找参数里文件的objectKey,如没有找到则用文件md5
					for (UploadFileRequest uploadFileRequest : fileList) {
						if (file.getOriginalFilename().equals(uploadFileRequest.getFileName())) {
							objectKey = uploadFileRequest.getObjectKey();
						}
					}
					if (StringUtils.isBlank(objectKey)) {
						objectKey = DigestUtils.md5DigestAsHex(fileInputStream);
					}

					Response<UploadFileResponse> uploadResult = fileObjectService.uploadFile(bucketName, folder, objectKey,
							fileInputStream);

					UploadFileResponse info = uploadResult.getData();
					if (info!=null) {
						// 上传成功返回对象url和objectKey
						successCount++;
					}
					info.setFileName(file.getOriginalFilename());
					uploadFileInfoList.add(info);

				} catch (IOException e) {
					UploadFileResponse info = new UploadFileResponse(500, "文件IO异常");
					info.setFileName(file.getOriginalFilename());
					uploadFileInfoList.add(info);
				} catch (Exception e) {
					UploadFileResponse info = new UploadFileResponse(500, "上传服务异常");
					info.setFileName(file.getOriginalFilename());
					uploadFileInfoList.add(info);
				}
			}
		}
		UploadFilesResponse response = new UploadFilesResponse();
		response.setSuccessCount(successCount);
		response.setUploadCount(files.length);
		response.setFileInfoList(uploadFileInfoList);
		Response<UploadFilesResponse> result = Response.data(response);
		return result;
	}

	@RequestMapping(value = "/resizePic", method = RequestMethod.POST)
	@ApiOperation(value = "对图片进行缩放，转换格式，压缩处理",notes = "返回图片url")
	public Response resizePicture(ResizePictureRequest param) {
		// 判断url是否为图片文件路径
		if (!ObsPictureProcessUtil.isImg(param.getImgUrl())) {
			return Response.failed("不支持的图片路径");
		}
		// 判断转换格式是否支持
		if (StringUtils.isNotBlank(param.getTargetFormat())) {
			String tempFormat = "." + param.getTargetFormat();
			if (!ObsPictureProcessUtil.isValid(tempFormat, ObsPictureProcessUtil.allowPicTypes)) {
				return Response.failed("不支持的图片格式");
			}
		}

		String imgUrl = param.getImgUrl();
		// 追加华为云操作前缀
		imgUrl += "?x-image-process=image";
		imgUrl = ObsPictureProcessUtil.resize(imgUrl, param.getWidth(), param.getHeight());
		imgUrl = ObsPictureProcessUtil.compQuality(imgUrl, param.getQuality());

		if (StringUtils.isNotBlank(param.getTargetFormat())) {
			imgUrl = ObsPictureProcessUtil.formatTransform(imgUrl, param.getTargetFormat());
		}
		Response<String> result = Response.success(imgUrl);
		return result;

	}

	@RequestMapping("/test")
	@ApiIgnore
	public Response test() {
		try {
			TimeUnit.SECONDS.sleep(11);
			return Response.success("等待时间11000毫秒");
			//return fileObjectService.test();
		}
		catch (Exception e){
			return Response.failed("测试失败");
		}

		//return Response.failed("测试失败");
	}

}
